
const fs = require('fs');

/**
 * 框架配置
 */
export interface FrameworkConfig {
    /**
     * 框架名称
     */
    framework:string;

    /**
     * 模块配置
     */
    modules:{
        [key:string]:{
            /**
             * 保留此模块
             */
            keep?:boolean;
            
            /**
             * 是否为基础模块
             */
            baseModule?:boolean;
    
            /**
             * 默认是否保留此模块
             */
            keepDefault?:boolean;
    
            /**
             * 模块描述
             */
            description?:string;
    
            /**
             * 库文件
             */
            libs?:string[];
    
            /**
             * 声明文件
             */
            types?:string[];
    
            /**
             * 模块依赖
             */
            dependences?:string[];
    
            /**
             * 模块源文件
             */
            sources?:string[];
    
            /**
             * 模块关键字
             */
            keywords?:string[];
    
            /**
             * 模块导出
             */
            exports?:string[];
    
            /**
             * Cocos依赖
             */
            cocosdeps?:string[];
        }
    }
}

/**
 * 框架配置器
 */
export class FrameworkConfigurator {

    /**
     * 配置对象
     */
    private _config:FrameworkConfig = null;

    /**
     * 构建模块树
     * @param configFile 模块配置文件
     */
    constructor(config:string|FrameworkConfig){
		if(typeof config == "string"){
			this._config = JSON.parse(fs.readFileSync(config, { encoding : 'utf-8' }));
		}else{
			this._config = config;
		}
    }

    /**
     * 保留模块数组
     * @param mnames 
     */
    public keepModules(mnames:string[]){
        if(mnames){
            for(let mname of mnames){
                this.keepModule(mname);
            }
        }
    }

    /**
     * 保留模块
     * @param mname 
     */
    public keepModule(mname:string){
        let module = this._config.modules[mname];
        if(module){
            if(!module.keep){
                module.keep = true;
                this.keepModules(module.dependences);
            }
        }
	}

    /**
     * 保留所有模块
     */
    public keepAllModules(){
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            module.keep = true;
        }
    }
	
	/**
	 * 收集模块
	 */
	public collectModules(){
		let modules:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep){
                modules.push(mname);
            }
        }
        return [... new Set(modules)];
	}

    /**
     * 收集源文件
     */
    public collectSources(){
        let sources:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep && module.sources){
                sources.push(...module.sources);
            }
        }
        return [... new Set(sources)];
    }

    /**
     * 收集库文件
     */
    public collectLibs(){
        let libs:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep && module.libs){
                libs.push(...module.libs);
            }
        }
        return [... new Set(libs)];
    }

    /**
     * 收集声明文件
     */
    public collectTypes(){
        let types:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep && module.types){
                types.push(...module.types);
            }
        }
        return [... new Set(types)];
    }

    /**
     * 收集导出
     */
    public collectExports(){
        let exports:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep && module.exports){
                exports.push(...module.exports);
            }
        }
        return [... new Set(exports)];
    }

    /**
     * 收集Cocos依赖
     */
    public collectCocosDeps(){
        let cocosdeps:string[] = [];
        for(let mname in this._config.modules){
            let module = this._config.modules[mname];
            if(module.keep && module.cocosdeps){
                cocosdeps.push(...module.cocosdeps);
            }
        }
        return [... new Set(cocosdeps)];
    }
}
